﻿using Natural.Attributes;
using Natural.Helpers;
using Natural.Model;
using System.Linq;
using System.Collections.Generic;
using System.Web;

namespace Natural.Providers
{
    [Impl(Type = ImplType.Provider, Name = "Executor", Strategy = "Default", Priority = 0)]
    public class DefaultExecutor : IExecutor
    {
        public void Execute(ActionContext context)
        {
            ActionRequest request = context.Request;
            ActionResponse response = context.Response;

            //construye las instancia de la accion
            Solver.Build(request.ActionInfo);
            //obbiene la estrategia a ejecutar
            ImplementInfo strategy = Strategy(request.ActionInfo.Strategies,request.Parameters);
            //executa la accion
            List<object> list = new List<object>(request.Parameters.Length + 1);
            list.Add(context);
            list.AddRange(request.Parameters);
            object[] parameters = list.ToArray();
            response.Result = ReflectionHelper.Invoke(strategy.Instance, Solver.EXECUTE, parameters);
            //notifica a todos los Observadores
            foreach (ImplementInfo observer in request.ActionInfo.Observers.OrderBy(p => p.Priority))
                ReflectionHelper.Invoke(observer.Instance, Solver.NOTIFY, parameters);
        }
        public static ImplementInfo Strategy(List<ImplementInfo> strategies, object[] parameters)
        {            
            if (strategies == null || strategies.Count == 0) return null;
            foreach (ImplementInfo strategyInfo in strategies.OrderBy(p => p.Priority))
            {
                if (strategyInfo.Instance.GetType().GetMethods().Where(p => p.Name == Solver.EVALUATE).Count() == 0)
                    return strategyInfo;
                // si contiene el metodo evaluate evalua la estrategia
                if ((bool)ReflectionHelper.Invoke(strategyInfo.Instance, Solver.EVALUATE, parameters))
                    return strategyInfo;
            }
            return null;
        }

    }
}
